Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / backend / page_node_manager.py

Displaying Raw • Download


meshchatx/src/backend/page_node_manager.py 22b4fcce096023ec706bab5449805e34a2912643 (22b4fcce) Text, 4.49 KB

T8b949e# SPDX-License-Identifier: 0BSD

T8b949e"""PageNodeManager: Manages the lifecycle of multiple PageNode instances.

Handles creation, deletion, persistence, start/stop, and announce
scheduling for page nodes. Each node gets its own subdirectory under
storage/page_nodes/<node_id>/.
"""

Tff7b72import T7ee787os
Tff7b72import T7ee787uuid

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787page_node Tff7b72import Te6edf3PageNode


Tff7b72class T56d364PageNodeManagerTb4b4b4:
T8b949e"""Manages multiple PageNode instances."""

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3storage_dirTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffpage_nodesTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffnodesTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3PageNodeTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}

Tff7b72def Td2a8ffload_nodesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Discover and load all persisted nodes from disk."""
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4:
Tff7b72return

Tff7b72for Te6edf3entry Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4:
Te6edf3node_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Te6edf3entryTb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3node_dirTb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3config Tff7b72= Te6edf3PageNodeTff7b72.Td2a8ffload_configTb4b4b4(Te6edf3node_dirTb4b4b4)
Tff7b72if Te6edf3config Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72continue
Te6edf3node_id Tff7b72= Te6edf3configTb4b4b4[Ta5d6ff"Ta5d6ffnode_idTa5d6ff"Tb4b4b4]
Tff7b72if Te6edf3node_id Tff7b72in Tff7b72selfTff7b72.Td2a8ffnodesTb4b4b4:
Tff7b72continue
Te6edf3node Tff7b72= Te6edf3PageNodeTb4b4b4(
Te6edf3node_idTff7b72=Te6edf3node_idTb4b4b4,
Te6edf3nameTff7b72=Te6edf3configTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3base_dirTff7b72=Te6edf3node_dirTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffnodesTb4b4b4[Te6edf3node_idTb4b4b4] Tff7b72= Te6edf3node

Tff7b72def Td2a8ffcreate_nodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3node_idTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e"""Create a new page node, persist its config, and return it."""
Tff7b72if Te6edf3node_id Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3node_id Tff7b72= Tffa657strTb4b4b4(Te6edf3uuidTff7b72.Td2a8ffuuid4Tb4b4b4(Tb4b4b4)Tb4b4b4)

Te6edf3node_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Te6edf3node_idTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3node_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)

Te6edf3node Tff7b72= Te6edf3PageNodeTb4b4b4(Te6edf3node_idTff7b72=Te6edf3node_idTb4b4b4, Te6edf3nameTff7b72=Te6edf3nameTb4b4b4, Te6edf3base_dirTff7b72=Te6edf3node_dirTb4b4b4)
Te6edf3nodeTff7b72.Td2a8ffsave_configTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffnodesTb4b4b4[Te6edf3node_idTb4b4b4] Tff7b72= Te6edf3node
Tff7b72return Te6edf3node

Tff7b72def Td2a8ffdelete_nodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3node_idTb4b4b4)Tb4b4b4:
T8b949e"""Stop and remove a node, deleting its directory."""
Te6edf3node Tff7b72= Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffgetTb4b4b4(Te6edf3node_idTb4b4b4)
Tff7b72if Te6edf3node Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72if Te6edf3nodeTff7b72.Td2a8ffrunningTb4b4b4:
Te6edf3nodeTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)

Tff7b72import T7ee787shutil

Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3nodeTff7b72.Td2a8ffbase_dirTb4b4b4, Te6edf3ignore_errorsTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72del Tff7b72selfTff7b72.Td2a8ffnodesTb4b4b4[Te6edf3node_idTb4b4b4]
Tff7b72return Tff7b72True

Tff7b72def Td2a8ffstart_nodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3node_idTb4b4b4)Tb4b4b4:
T8b949e"""Set up and start serving for a specific node."""
Te6edf3node Tff7b72= Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffgetTb4b4b4(Te6edf3node_idTb4b4b4)
Tff7b72if Te6edf3node Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffNode Tffd700{Te6edf3node_idTffd700}Ta5d6ff not foundTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3nodeTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72return Te6edf3nodeTff7b72.Td2a8ffget_destination_hashTb4b4b4(Tb4b4b4)

Tff7b72return Te6edf3nodeTff7b72.Td2a8ffsetupTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffstop_nodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3node_idTb4b4b4)Tb4b4b4:
T8b949e"""Stop serving for a specific node."""
Te6edf3node Tff7b72= Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffgetTb4b4b4(Te6edf3node_idTb4b4b4)
Tff7b72if Te6edf3node Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffNode Tffd700{Te6edf3node_idTffd700}Ta5d6ff not foundTa5d6ff"Tb4b4b4)
Te6edf3nodeTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffstart_allTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Start all loaded nodes."""
Tff7b72for Te6edf3node_id Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstart_nodeTb4b4b4(Te6edf3node_idTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to start page node Tffd700{Te6edf3node_idTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffstop_allTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Stop all running nodes."""
Tff7b72for Te6edf3node_id Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstop_nodeTb4b4b4(Te6edf3node_idTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to stop page node Tffd700{Te6edf3node_idTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffannounce_nodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3node_idTb4b4b4)Tb4b4b4:
T8b949e"""Send an announce for a specific node."""
Te6edf3node Tff7b72= Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffgetTb4b4b4(Te6edf3node_idTb4b4b4)
Tff7b72if Te6edf3node Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffNode Tffd700{Te6edf3node_idTffd700}Ta5d6ff not foundTa5d6ff"Tb4b4b4)
Te6edf3nodeTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffannounce_allTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Send announces for all running nodes."""
Tff7b72for Te6edf3node Tff7b72in Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3nodeTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3nodeTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to announce page node Tffd700{Te6edf3nodeTff7b72.Td2a8ffnode_idTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffrename_nodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3node_idTb4b4b4, Te6edf3new_nameTb4b4b4)Tb4b4b4:
T8b949e"""Rename a node and persist the change."""
Te6edf3node Tff7b72= Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffgetTb4b4b4(Te6edf3node_idTb4b4b4)
Tff7b72if Te6edf3node Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffNode Tffd700{Te6edf3node_idTffd700}Ta5d6ff not foundTa5d6ff"Tb4b4b4)
Te6edf3nodeTff7b72.Td2a8ffname Tff7b72= Te6edf3new_name
Te6edf3nodeTff7b72.Td2a8ffsave_configTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffget_nodeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3node_idTb4b4b4)Tb4b4b4:
T8b949e"""Return a node by id or None."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffgetTb4b4b4(Te6edf3node_idTb4b4b4)

Tff7b72def Td2a8fflist_nodesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Return status dicts for all nodes."""
Tff7b72return Tb4b4b4[Te6edf3nodeTff7b72.Td2a8ffget_statusTb4b4b4(Tb4b4b4) Tff7b72for Te6edf3node Tff7b72in Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4]

Tff7b72def Td2a8ffteardownTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Stop all nodes and clear state."""
Tff7b72selfTff7b72.Td2a8ffstop_allTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffnodesTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────